BIM Coordinator Program (INT) April 22, 2024
Find the next step in your career as a Graphisoft Certified BIM Coordinator!
Archicad C++ API
About Archicad add-on development using the C++ API.

CMake and subdirectories

MudratDetector
Enthusiast

AC27 | WIN10 | VS2019, Toolset 142

.

The learning curve is starting to flatten out...  but here is something new for me.

 

I have a project [JHP_Audit] with a folder structure like this:

MudratDetector_0-1706199052535.png

My CMakeLists.txt file is in the ..\JHP_Audit\ folder and is here:

 

 

cmake_minimum_required (VERSION 3.16)

include (Tools/CMakeCommon.cmake)

set (API_DEVKIT_DIR $ENV{AC_API_DEVKIT_DIR} CACHE PATH "API DevKit directory.")

if (GITHUB_BUILD)
    include(${CMAKE_BINARY_DIR}/conan_paths.cmake)
    set (API_DEVKIT_DIR ${CONAN_ARCHICAD-APIDEVKIT_ROOT}/bin)
endif ()

set_property (GLOBAL PROPERTY USE_FOLDERS ON)

# set (CMAKE_CONFIGURATION_TYPES Debug;Release;RelWithDebInfo)
set (CMAKE_CONFIGURATION_TYPES Release)
set (AC_API_DEVKIT_DIR ${API_DEVKIT_DIR} CACHE PATH "API DevKit directory.")
set (AC_ADDON_NAME "JHP_Audit" CACHE STRING "AddOn Name")
set (AC_ADDON_LANGUAGE "INT" CACHE STRING "Add-On language code.")

project (${AC_ADDON_NAME} CXX)

message( STATUS ">>> AC_API_DEVKIT_DIR: $ENV{AC_API_DEVKIT_DIR}")
DetectACVersion (${AC_API_DEVKIT_DIR} ACVersion)
message (STATUS "Archicad Version: ${ACVersion}")

set (AddOnFolder .)
message (STATUS ">>> AddOnFolder: ${AddOnFolder}")
SetGlobalCompilerDefinitions ()
GenerateAddOnProject (${ACVersion} ${AC_API_DEVKIT_DIR} ${AC_ADDON_NAME} ${AddOnFolder} ${AC_ADDON_LANGUAGE})
set_target_properties(${AC_ADDON_NAME} PROPERTIES LINKER_LANGUAGE CXX)

 

 

The main file is JHP_Audit.cpp and in the ..\JHP_Audit\Src\ folder.

I have other *.cpp and *.h files in:

..\JHP_Audit\Src\Audits\ 

..\JHP_Audit\Src\JHPCommon\

..\JHP_Audit\Src\LiveAudit\

..\JHP_Audit\Src\Report\

 

I am receiving "error LNK2019: unresolved external symbol" errors when I build and I suspect it is because CMake does not know about these additional files in the folders listed above.  Research in that direction reveals target_sources() as the CMake edit to resolve this.

 

CMake documentation is not clear to me for the exact syntax I should use to accomplish this.  
I will try:
..\JHP_Audit\CMakeLists.txt

 

 

project(JHP_Audit)

add_executable(JHP_Audit "")

add_subdirectory(./Src/Audits)
add_subdirectory(./Src/JHPCommon)
add_subdirectory(./Src/LiveAudit)
add_subdirectory(./Src/Report)

 

 

..\JHP_Audit\Src\<each subdirectory>\CMakeLists.txt.  Filenames for .ccp and .h as required.

 

 

target_sources(JHP_Audit
    PRIVATE
        Audits_Beams.cpp
        Audits_Beams.h
        Audits_Dimensions.cpp
        Audits_Dimensions.h
        #<all others>.cpp
        #<all others>.h
)

target_include_directories(JHP_Audit PUBLIC ${CMAKE_CURRENT_LIST_DIR})

 

 

- - I am not clear on my use of JHP_Audit in the code snippets above - - Do I need full path, relative path?  Is it a logical name that I have defined earlier?  I know files used by target_sources() can stand alone without path
- - My example linked below uses add_library() that I have swapped with add_executable() - - Is that necessary?  Is that accurate?

- - I currenlty do not have a definition for CMAKE_CURRENT_LIST_DIR.  it is created and appended on the fly with each of the passes through the subdirectory CMakeLists.txt files.

- - Do I need to delete cache and generate CMake cache to load variables for each of the five CMakeLists.txt files?

 

Source of information:

https://crascit.com/2016/01/31/enhanced-source-file-handling-with-target_sources/ 

Thanks as always,

chris

Chris Gilmer
Intel i9-12950HX CPU @ 2.30GHz, 16 cores
NVIDIA GeForce RTX 3080
48.0 GB RAM
Windows 10 Pro 64-bit
3 REPLIES 3
MudratDetector
Enthusiast

Update a few minutes later:

After implementing the above edits, a build will still generate "error LNK2019: unresolved external symbol" and ultimately "JHP_Audit.apx : fatal error LNK1120: 29 unresolved externals".

But now there are errors associatred with the .ccp files and .h files in the subdirectories.  And they seem to relate to missing files that are generic and would have been prior issues in other add-ons.

 

G:\dev\v27\JHP_Audit\out\build\x64-Release\Release\JHP_Audit.apx : fatal error LNK1120: 29 unresolved externals 
    Building Custom Rule G:/dev/v27/JHP_Audit/CMakeLists.txt
    Audits_Beams.cpp
G:\dev\v27\JHP_Audit\Src\APIEnvir.h(22,11): fatal error C1083: Cannot open include file: 'Win32Interface.hpp': No such file or directory 
    Audits_Dimensions.cpp
G:\dev\v27\JHP_Audit\Src\APIEnvir.h(22,11): fatal error C1083: Cannot open include file: 'Win32Interface.hpp': No such file or directory 
    Audits_Generic.cpp
G:\dev\v27\JHP_Audit\Src\APIEnvir.h(22,11): fatal error C1083: Cannot open include file: 'Win32Interface.hpp': No such file or directory 
    Audits_Railings.cpp
G:\dev\v27\JHP_Audit\Src\APIEnvir.h(22,11): fatal error C1083: Cannot open include file: 'Win32Interface.hpp': No such file or directory 
    Audits_Walls.cpp
G:\dev\v27\JHP_Audit\Src\APIEnvir.h(22,11): fatal error C1083: Cannot open include file: 'Win32Interface.hpp': No such file or directory 
    Audits_Windows.cpp
G:\dev\v27\JHP_Audit\Src\APIEnvir.h(22,11): fatal error C1083: Cannot open include file: 'Win32Interface.hpp': No such file or directory 
    Format.cpp
G:\dev\v27\JHP_Audit\Src\APIEnvir.h(22,11): fatal error C1083: Cannot open include file: 'Win32Interface.hpp': No such file or directory 
    Math.cpp
G:\dev\v27\JHP_Audit\Src\JHPCommon\Math.h(3,13): fatal error C1083: Cannot open include file: 'ACAPinc.h': No such file or directory 
    Utilities.cpp
G:\dev\v27\JHP_Audit\Src\JHPCommon\Utilities.h(3,13): fatal error C1083: Cannot open include file: 'ACAPinc.h': No such file or directory 
    LiveAudit.cpp
G:\dev\v27\JHP_Audit\Src\APIEnvir.h(22,11): fatal error C1083: Cannot open include file: 'Win32Interface.hpp': No such file or directory 
    LiveAudit_Palette.cpp
G:\dev\v27\JHP_Audit\Src\APIEnvir.h(22,11): fatal error C1083: Cannot open include file: 'Win32Interface.hpp': No such file or directory 
    AuditReport.cpp
G:\dev\v27\JHP_Audit\Src\APIEnvir.h(22,11): fatal error C1083: Cannot open include file: 'Win32Interface.hpp': No such file or directory 
    Generating Code...

Build All failed.

 

Anyways, off to chase that down...

Chris Gilmer
Intel i9-12950HX CPU @ 2.30GHz, 16 cores
NVIDIA GeForce RTX 3080
48.0 GB RAM
Windows 10 Pro 64-bit

I have made some progress at this add-on project with source code in various subdirectories and getting my CMakeLists.txt file set with the right commands.  I am currently at a roadblock that I cannot resolve.

 

..\JHP_Audit\CMakeLists.txt

[problem area - line 24]

MudratDetector_0-1707248883624.png

[complete file]

 

cmake_minimum_required (VERSION 3.16)
message (STATUS "CMake version >>> " ${CMAKE_VERSION})

include (Tools/CMakeCommon.cmake)

set (API_DEVKIT_DIR $ENV{AC_API_DEVKIT_DIR} CACHE PATH "API DevKit directory.")

set_property (GLOBAL PROPERTY USE_FOLDERS ON)

set (CMAKE_CONFIGURATION_TYPES Debug;Release;RelWithDebInfo)

set (AC_API_DEVKIT_DIR ${API_DEVKIT_DIR} CACHE PATH "API DevKit directory.")
set (AC_ADDON_NAME "JHP_Audit" CACHE STRING "AddOn Name")
set (AC_ADDON_LANGUAGE "INT" CACHE STRING "Add-On language code.")

project (${AC_ADDON_NAME} CXX)
add_subdirectory (Src)

DetectACVersion (${AC_API_DEVKIT_DIR} ACVersion)

add_library(AuditLib STATIC "")
target_include_directories (AuditLib PUBLIC
	${AddOnSourcesFolderAbsolute}
	${AC_API_DEVKIT_DIR}Support/Inc
	${AC_API_DEVKIT_DIR}Support/Modules/GSUtils
	${AC_API_DEVKIT_DIR}Support/Modules/GSRoot
)

set (AddOnFolder .)
SetGlobalCompilerDefinitions ()
GenerateAddOnProject (${ACVersion} ${AC_API_DEVKIT_DIR} ${AC_ADDON_NAME} ${AddOnFolder} ${AC_ADDON_LANGUAGE})
set_target_properties(${AC_ADDON_NAME} PROPERTIES LINKER_LANGUAGE CXX)

 

 

..\JHP_Audit\Src\CMakeLists.txt

[problem area - line 13]

 

MudratDetector_5-1707249631861.png

[complete file]

 

add_subdirectory(Audits)
add_subdirectory(JHPCommon)
add_subdirectory(LiveAudit)
add_subdirectory(Report)

include_directories(
	${AddOnSourcesFolderAbsolute}Audits
	${AddOnSourcesFolderAbsolute}JHPCommon
	${AddOnSourcesFolderAbsolute}LiveAudit
	${AddOnSourcesFolderAbsolute}Report
)

add_executable (AuditLib_Src
	${AddOnSourcesFolderAbsolute}JHP_Audit.cpp
	${AddOnSourcesFolderAbsolute}Audits/Audits_Beams.cpp
	${AddOnSourcesFolderAbsolute}Audits/Audits_Beams.h
	${AddOnSourcesFolderAbsolute}Audits/Audits_Dimensions.cpp
	${AddOnSourcesFolderAbsolute}Audits/Audits_Dimensions.h
	${AddOnSourcesFolderAbsolute}Audits/Audits_Generic.cpp
	${AddOnSourcesFolderAbsolute}Audits/Audits_Generic.h
	${AddOnSourcesFolderAbsolute}Audits/Audits_Railings.cpp
	${AddOnSourcesFolderAbsolute}Audits/Audits_Railings.h
	${AddOnSourcesFolderAbsolute}Audits/Audits_Walls.cpp
	${AddOnSourcesFolderAbsolute}Audits/Audits_Walls.h
	${AddOnSourcesFolderAbsolute}Audits/Audits_Windows.cpp
	${AddOnSourcesFolderAbsolute}Audits/Audits_Windows.h
	${AddOnSourcesFolderAbsolute}JHPCommon/Format.cpp
	${AddOnSourcesFolderAbsolute}JHPCommon/Format.h
	${AddOnSourcesFolderAbsolute}JHPCommon/Math.cpp
	${AddOnSourcesFolderAbsolute}JHPCommon/Math.h
	${AddOnSourcesFolderAbsolute}JHPCommon/Utilities.cpp
	${AddOnSourcesFolderAbsolute}JHPCommon/Utilities.h
	${AddOnSourcesFolderAbsolute}LiveAudit/LiveAudit.cpp
	${AddOnSourcesFolderAbsolute}LiveAudit/LiveAudit.h
	${AddOnSourcesFolderAbsolute}LiveAudit/LiveAudit_Palette.cpp
	${AddOnSourcesFolderAbsolute}LiveAudit/LiveAudit_Palette.hpp
	${AddOnSourcesFolderAbsolute}Report/AuditReport.cpp
	${AddOnSourcesFolderAbsolute}Report/AuditReport.h
)

 

 

The error message when saving the CMakeLists.txt edits:

[with the logical target names different - AuditLib and AuditLib_Src]

 

1> [CMake] CMake Error at G:\dev\v27\JHP_Audit\CMakeLists.txt:24 (add_library):
1> [CMake]   No SOURCES given to target: AuditLib
1> [CMake] 
1> [CMake] 
1> [CMake] CMake Generate step failed.  Build files cannot be regenerated correctly.

 

I believe this is because line 24 in the root CMakeLists file uses AuditLib as the logical name for the target and line 13 in the subfolder CMakeLists file uses AutoLib_Src as the logical name for the target.

 

[with the logical target names the same - AuditLib and AuditLib]

 

1> [CMake] CMake Error at G:\dev\v27\JHP_Audit\CMakeLists.txt:24 (add_library):
1> [CMake]   add_library cannot create target "AuditLib" because another target with the
1> [CMake]   same name already exists.  The existing target is an executable created in
1> [CMake]   source directory "G:/dev/v27/JHP_Audit/Src".  See documentation for policy
1> [CMake]   CMP0002 for more details.

 

This is because line 24 in the root CMakeLists file uses AuditLib as the logical name for the target and line 13 in the subfolder CMakeLists file uses AutoLib as the logical name for the target.

It appears the neither one of the options is correct.

Am I understanding this correctly?
Am I missing additional commands that allow one of these options to work?

Am I close to the correct way for doing this?

Has anyone ever used CMake to build a project with source files in multiple directories?
And finally - - Is anyone snow skiing at Lake Tahoe next week?  I will gladly buy beer for a rousing discussion of CMake and subdirectories...

 

All the best - chris

Chris Gilmer
Intel i9-12950HX CPU @ 2.30GHz, 16 cores
NVIDIA GeForce RTX 3080
48.0 GB RAM
Windows 10 Pro 64-bit
MudratDetector
Enthusiast

My solution - - 

Get rid of subdirectories that contain additional source files.  All source files are in the single parent directory now and CMakeLists issues seem to have magically vanished.

 

Tahoe update - - 9" [23 cm] powder day last Thursday was EPIC!  And the promise of beer for a rousing discussion of CMake and subdirectories...  ...produced zero takers.  Oh well.

 

 

Chris

Chris Gilmer
Intel i9-12950HX CPU @ 2.30GHz, 16 cores
NVIDIA GeForce RTX 3080
48.0 GB RAM
Windows 10 Pro 64-bit
Learn and get certified!