Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

23.06.2015, 09:05

CMake, Clang und LLVM Sanitizer

Hi, ich habe begonnen meinen Sourcecode etwas umzustrukturieren und eine ganze Reihe Unittests zu schreiben. Dabei ist mir wieder in den Sinn gekommen, dass es ja die LLVM Address und Memory Sanitizer gibt um ein paar weitere Fehlerquellen zu finden (use-after-free, double-free, memory leaks, uninitialized reads etc.). Dabei sieht meine CMakeLists.txt jetzt so aus:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
cmake_minimum_required (VERSION 2.8)
project (rage)

# place libs and executable where CMakeLists.txt is located
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR})
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR})

# apply some flags
set(DEFAULT_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -std=c++11 -Werror -Wall -Wfatal-errors")
set(DEFAULT_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")

# include local headers
include_directories(include)

# list all dependencies
SET(RAGE_DEPENDENCIES
    sfml-system
    sfml-graphics
    sfml-window
    sfml-audio
    thor
)

# -----------------------------------------------------------------------------
# group sources
set(RAGE_UTILS_SOURCE
    src/utils/algorithm.cpp
    src/utils/config_file.cpp
    src/utils/pathfinder.cpp
    src/utils/unionfind.cpp
)

set(RAGE_UTILS_TEST_SOURCE
    test_suite/utils/algorithm.cpp
    test_suite/utils/config_file.cpp
    test_suite/utils/enum_map.cpp
    test_suite/utils/pathfinder.cpp
    test_suite/utils/priority_queue.cpp
    test_suite/utils/unionfind.cpp
)

# -----------------------------------------------------------------------------
# Build shared libs from sources
add_library(rage-utils SHARED ${RAGE_UTILS_SOURCE})

set(RAGE_SHARED_LIBS
    rage-utils
)

# -----------------------------------------------------------------------------
# Build and run unit tests with address sanitizer
set(CMAKE_CXX_FLAGS "${DEFAULT_CXX_FLAGS} -fsanitize=address")
set(CMAKE_EXE_LINKER_FLAGS "${DEFAULT_LINKER_FLAGS} -fsanitize=address")

add_executable(rage_test_asan
    test_suite/main.cpp
    ${RAGE_UTILS_TEST_SOURCE}
    ${RAGE_UTILS_SOURCE}
)

target_link_libraries(rage_test_asan
    boost_unit_test_framework
    ${RAGE_DEPENDENCIES}
)

add_custom_command(TARGET rage_test_asan
    POST_BUILD
    COMMAND ../rage_test_asan --output-on-failure
)

# -----------------------------------------------------------------------------
# Build and run unit tests with memory sanitizer
set(CMAKE_CXX_FLAGS "${DEFAULT_CXX_FLAGS} -fsanitize=memory")
set(CMAKE_EXE_LINKER_FLAGS "${DEFAULT_LINKER_FLAGS} -fsanitize=memory")

add_executable(rage_test_msan
    test_suite/main.cpp
    ${RAGE_UTILS_TEST_SOURCE}
    ${RAGE_UTILS_SOURCE}
)

target_link_libraries(rage_test_msan
    boost_unit_test_framework
    ${RAGE_DEPENDENCIES}
)

add_custom_command(TARGET rage_test_msan
    POST_BUILD
    COMMAND ../rage_test_msan --output-on-failure
)

# -----------------------------------------------------------------------------
# Build game
set(CMAKE_CXX_FLAGS "${DEFAULT_CXX_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${DEFAULT_LINKER_FLAGS}")
add_executable(rage
    src/main.cpp
)

target_link_libraries(rage
    ${RAGE_DEPENDENCIES}
    ${RAGE_SHARED_LIBS}
)


Hat jemand Erfahrung im Umgang mit den Sanitizern? Hat jemand einen Tipp wie ich meinen Buildprozess dahingehend optimieren kann, dass ich asan und msan zusammen ausführen kann? (Bin mir nicht sicher ob das geht, aber im Moment muss der Testcode ja 2x kompiliert werden).

Btw baue ich outside-source in einem build-directory. (Daher die ../bla)

LG Glocke

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »Glocke« (23.06.2015, 10:14)


Tobiking

1x Rätselkönig

  • Private Nachricht senden

2

23.06.2015, 13:16


Hat jemand Erfahrung im Umgang mit den Sanitizern? Hat jemand einen Tipp wie ich meinen Buildprozess dahingehend optimieren kann, dass ich asan und msan zusammen ausführen kann? (Bin mir nicht sicher ob das geht, aber im Moment muss der Testcode ja 2x kompiliert werden).

Fehlt dir da einfach nur wie der Parameter aussehen muss? Laut Clang Doku ist sanitize eine Liste: "-f[no-]sanitize=check1,check2,..."


Btw baue ich outside-source in einem build-directory. (Daher die ../bla)

Das mit dem separaten Build directory ist richtig und gut. Aber gerade dann solltest du keine fixen (relative) Pfade angehen, sondern die Variablen nutzen.

3

23.06.2015, 17:51

Fehlt dir da einfach nur wie der Parameter aussehen muss? Laut Clang Doku ist sanitize eine Liste: "-f[no-]sanitize=check1,check2,..."

Uuuups, ja genau das xD RTFM wäre was für mich gewesen :dash:
Danke :)

Das mit dem separaten Build directory ist richtig und gut. Aber gerade dann solltest du keine fixen (relative) Pfade angehen, sondern die Variablen nutzen.

Guter Punkt, ich hab die Pfadangaben jetzt erstmal entfernt, d.h. die Binaries landen im build/-Verzeichnis. Wie würdest du es denn konfigurieren?

Nach einigen Änderungen sieht die CMake-File jetzt so aus - weiteres Feedback ist herzlich willkommen :)

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
cmake_minimum_required (VERSION 2.8)
project (rage)

# apply some flags
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Werror -Wall -Wfatal-errors -g")

# include local headers
include_directories(include)

# list all dependencies
SET(RAGE_DEPENDENCIES
    sfml-system
    sfml-graphics
    sfml-window
    sfml-audio
    thor
)

# -----------------------------------------------------------------------------
# group sources
set(RAGE_UTILS_SOURCE
    src/utils/algorithm.cpp
    src/utils/config_file.cpp
    src/utils/pathfinder.cpp
    src/utils/unionfind.cpp
)

set(RAGE_UTILS_TEST_SOURCE
    test_suite/utils/algorithm.cpp
    test_suite/utils/config_file.cpp
    test_suite/utils/enum_map.cpp
    test_suite/utils/pathfinder.cpp
    test_suite/utils/priority_queue.cpp
    test_suite/utils/unionfind.cpp
)

# -----------------------------------------------------------------------------
# Build and run unit test with sanitizer
add_executable(rage_test
    test_suite/main.cpp
    # unit- and integration tests
    ${RAGE_UTILS_TEST_SOURCE}
    # actual source
    ${RAGE_UTILS_SOURCE}
)

set_target_properties(rage_test PROPERTIES COMPILE_FLAGS "-fsanitize=address,undefined")
set_target_properties(rage_test PROPERTIES LINK_FLAGS "-fsanitize=address,undefined")

target_link_libraries(rage_test
    boost_unit_test_framework
    # general dependencies
    ${RAGE_DEPENDENCIES}
)

add_custom_command(TARGET rage_test
    POST_BUILD
    COMMAND rage_test --output-on-failure
)

# -----------------------------------------------------------------------------
# Build shared libs and game executable
add_executable(rage
    src/main.cpp
    # actual source
    ${RAGE_UTILS_SOURCE}
)

add_dependencies(rage rage_test)

target_link_libraries(rage
    # general dependencies
    ${RAGE_DEPENDENCIES}
)

Tobiking

1x Rätselkönig

  • Private Nachricht senden

4

23.06.2015, 19:00


Guter Punkt, ich hab die Pfadangaben jetzt erstmal entfernt, d.h. die Binaries landen im build/-Verzeichnis. Wie würdest du es denn konfigurieren?

Wo die Executables am Ende landen ist ein wenig Geschmacksache. Ein fixer Ort macht es einfacher wenn die Anwendung weitere Ressourcen benötigt. Man kann sich aber Batch/Shell Skripte vorbereiten, in die CMake das passenden working directory etc. einträgt. Auf der anderen Seite möchte man vielleicht irgendwann verschiedene Builds erstellen. Ich denke da an 32/64 Bit oder auch mit/ohne Debug. Man könnte sie mit affixe versehen, ist aber auch irgendwann etwas nervig. Ich mag da komplett separate Build Ordner mit den Executables drin.

Mir ging es bei deiner ersten Lösung auch hauptsächlich darum das du z.B. mit ../rage_test_msan auf die Executable zugegriffen hast. Damit beschränkst du die Lage des Build Ordner auf eine Ebene innerhalb des Source Ordner. Nutzt du stattdessen ${EXECUTABLE_OUTPUT_PATH}/rage_test_msan, kann der Build Ordner überall liegen und du kannst auch den executable Pfad anpassen wie du willst ohne das du weitere Änderungen durchführen musst.

5

23.06.2015, 20:16

Nutzt du stattdessen ${EXECUTABLE_OUTPUT_PATH}/rage_test_msan, kann der Build Ordner überall liegen und du kannst auch den executable Pfad anpassen wie du willst ohne das du weitere Änderungen durchführen musst.


Ach das meintest du :D Ok, danke :)

Werbeanzeige