Correct cmake setup to include headers - cmake

I have a project structured like this:
─root
├──src
│ ├──main.cpp
│ └──CMakeLists.txt[2]
├──build
├──out
├──inc
├──dep
│ ├──log
│ │ ├──include
│ │ │ └──log.h
│ │ ├──src
│ │ │ └──log.cpp
│ │ └──CMakeLists.txt[4]
│ └──CMakeLists.txt[3]
└──CMakeLists.txt[1]
Under dep I have a logging library, which is an external git repository with his own CMakeLists.txt file.
The main CMakeLists.txt (marked as [1]) is:
cmake_minimum_required(VERSION 2.6)
set(APP_ROOT ${PROJECT_SOURCE_DIR})
add_subdirectory(dep)
add_subdirectory(src)
The CMakeLists.txt (marked as [2]) for the current project code is:
add_executable(app main.cpp)
target_link_libraries(app log)
include_directories("${APP_ROOT}/inc")
The CMakeLists.txt (marked as [3]) for the dependencies is:
add_subdirectory(log)
What I'm trying to do is to have the contents of the dep/log/include folder copied inside a new folder called inc/log, so that in main.cpp I can write something like #include <log/log.h>, but I don't understand how. I would like to avoid editing the CMakeLists.txt of the logger project.

My solution: in /dep/CMakeLists.txt I added
file(MAKE_DIRECTORY "${APP_ROOT}/inc/log")
file(COPY "log/include/" DESTINATION "${APP_ROOT}/inc/log")

Related

Multiple undefined reference during linking of a CMake project using ARM toolchain

I'm developing a build system using CMake to build applications using the arm-none-eabi toolchain.
This is my folder structure:
project/
├── apps/
│ ├── test_app
│ │ ├── inc/
│ │ ├── src/
│ │ ├── CMakeLists.txt
├── arch/
│ ├── CMSIS/
│ ├── include/
│ ├── startup/
│ ├── CMakeLists.txt
├── cmake/
│ ├── toolchain-samd51.cmake
├── CMakeLists.txt
This is my top level CMakeLists.txt:
cmake_minimum_required(VERSION 3.17)
project(SMALL-FW LANGUAGES C)
add_subdirectory(arch)
add_subdirectory(apps/test_app)
This is the toolchain cmake file:
# Set target architecture
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)
# Set compiler to use
set(CMAKE_C_COMPILER "arm-none-eabi-gcc")
#set(CMAKE_LINKER "arm-none-eabi-ld")
# Clear default compiler and linker flags.
set(CMAKE_C_FLAGS "")
set(CMAKE_C_LINK_FLAGS "")
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
# FIX - Bypass compiler check
set(CMAKE_C_COMPILER_FORCED TRUE)
# Define common compiler and linker flags
set(ARM_OPTIONS
-mthumb
-mabi=aapcs-linux
-mcpu=cortex-m4
-mfpu=fpv4-sp-d16
-mfloat-abi=softfp
--specs=nano.specs
-mlong-calls
-DSAMD51
)
# Define compiler specific flags
add_compile_options(
${ARM_OPTIONS}
-D__SAMD51J19A__
-ffunction-sections
-Wall
)
# Define linker specific flags
add_link_options(
${ARM_OPTIONS}
#--specs=nano.specs
LINKER:--gc-sections
)
This is the CMakeList.txt inside the arch folder:
add_library(asf OBJECT
startup/startup_samd51.c
startup/system_samd51.c
)
# Every target that links against asf needs to know where the ASF headers are.
target_include_directories(asf PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/CMSIS/Include
${CMAKE_CURRENT_SOURCE_DIR}/include
)
# Use the custom linker script provided with ASF.
target_link_options(asf PUBLIC
-T${CMAKE_CURRENT_SOURCE_DIR}/startup/samd51j19a_flash.ld
)
And this is the app CMakeLists.txt:
add_executable(APP)
target_sources(APP PRIVATE src/main.c src/module.c)
target_include_directories(APP PRIVATE inc/)
target_link_libraries(APP asf)
CMake is running fine when the CMAKE_C_COMPILER_FORCED options is set to true, but when I try to make the project it fails with multiple undefined references errors like the next one:
/build/arm-none-eabi-newlib/src/build-nano/arm-none-eabi/thumb/v7e-m+fp/softfp/newlib/libc/reent/../../../../../../../../newlib-4.2.0.20211231/newlib/libc/reent/sbrkr.c:51: undefined reference to _sbrk'`
I have tried using nosys.specs flag but similar errors occurs.
Try this, it looks like typo
# Define linker specific flags
add_link_options(
${ARM_OPTIONS}
--specs=nano.specs
--gc-sections
)

take the structure of any project

I have seen the project structure on readMe, how can I take this structure of my project, any program? any website. doesn't seems right to me to create by hand?
Yes, there is a very simple way to get it.
Navigate to the root folder of your project and run tree from your terminal. You should get something like this:
project_root
│ README.md
│
└───some_folder
│ │ another_file.txt
│ │ some_code.code
│ │
│ └───some_subfolder
│ │ some_more_code.txt
│ │ another_file.txt
│ │ a_picture.png
│ │ ...
│
└───another_folder
│ more_files.txt
│ more_code.code
...
Now you can copy and paste this tree into your README file, wrapping it in triple backticks - ``` to get the markdown styling.
https://ascii-tree-generator.com/ --> by hand ***
or ***
tree command in powershell --> auto

Modern CMake - setup libraries targets inside project

My project structure presents as follows:
── src
├── app
│ ├── first_app
│ │ ├── include
│ │ └── src
│ │ └── CMakeLists.txt
│ ├── second_app
│ │ └── ...
├── lib
│ ├── first_lib
│ | ├── include
│ | └── src
│ | └── CMakeLists.txt
│ ├── second_lib
│ | ├── include
│ | └── src
│ | └── CMakeLists.txt
├── CMakeLists.txt
first_app uses both first_lib and second_lib. I would like to force CMake to find all dependencies (libraries and include headers) using
target_link_libraries(first_app first_lib::first_lib second_lib::second_lib).
I would like to ask two questions:
What command should be used to export first_lib::first_lib in ./src/lib/first_lib/CMakeLists.txt?
How to make first_lib::first_lib visible in ./src/app/first_app/CMakeLists.txt?
Supposing you create your lib using add_library(first_lib ...)
1) I would use:
include(GNUInstallDirs)
install(TARGETS first_lib
EXPORT FirstLibTargets
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/first_lib
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
src: https://github.com/Mizux/cmake-cpp/blob/master/Foo/CMakeLists.txt#L24
then you can install the export file using:
install(EXPORT FirstLibTargets
NAMESPACE first_lib::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/FirstLib
COMPONENT Devel)
src: https://github.com/Mizux/cmake-cpp/blob/master/CMakeLists.txt
note: I don't know if you can install target alias (i.e. install(TARGETS first_lib::first_lib) and/or have an export file with differents namespace (i.e. first_lib:: second_lib::)
2) simply use in first_lib/CMakeLists.txt:
add_library(first_lib::first_lib ALIAS first_lib) just after your add_library.
so first_app could always use first_lib::first-lib to retrieve this target dependencies what ever if you use a Meta CMake (i.e. add_subdirectory()) or find_package().
e.g. https://github.com/Mizux/cmake-cpp/blob/master/Foo/CMakeLists.txt

From list of directories, copy all subfolders to new location each with own folder per directory

I've searched around and can't seem to find a solution on my own so I'm asking for help!
I have a list of ~100 file locations/directories. They're located on the network and I need to grab them all and store them locally. I have some experience with VBA so I was going to try and use that (perhaps put the directories in a spread sheet and run a macro off that..)
When I store them locally I need to preserve the names of the directories they came from.
Any help would be MASSIVELY appreciated, automating this is becoming more and more necessary as I'm being sent more directories and a manual process will not scale well as this moves forward.
Any help at all, pointing me in a direction or offering advice is GREATLY appreciated.
Cheers
You can use the Copy-Item cmdlet in PowerShell combined with the -recurse and -container switches to copy and preserve folder structure! It's awesome for backing up a full network folder, and all sub-folders too!
Here is my Source directory.
C:\temp\stack>tree /F
Folder PATH listing
Volume serial number is 0000000B 9215:D0CB
C:.
├───Dest
└───Source
├───1
│ Archive.rar
│ File01.bmp
│
├───2
│ Archive.rar
│ File01.bmp
│
├───3
│ Archive.rar
│ File01.bmp
│
└───4
3.txt
Archive.rar
File01.bmp
Ham.txt
As you can see, I have some files and folders in Source with subfolders and subfiles in each. With this one simple PowerShell command though, I can move that whole structure easily into Dest.
copy-item -Path c:\temp\stack\source -Destination C:\temp\stack\Dest -Container -Recurse
Now I have that whole structure maintained in the Dest folder as well.
C:\temp\stack>tree /F
Folder PATH listing
Volume serial number is 000000DE 9215:D0CB
C:.
├───Dest
│ ├───1
│ │ Archive.rar
│ │ File01.bmp
│ │
│ ├───2
│ │ Archive.rar
│ │ File01.bmp
│ │
│ ├───3
│ │ Archive.rar
│ │ File01.bmp
│ │
│ └───4
│ 3.txt
│ Archive.rar
│ File01.bmp
│ Ham.txt
Copy-Item will work as mentioned. robocopy was also built for this exact purpose, and will run in cmd or Powershell. Run robocopy /? for usage info.
You probably want something like:
robocopy "Y:\Network\Source\Location" "C:\Local\Machine\Destination\Location" /E
/E Means to copy the directory and all subdirectories.

How can I have Wintersmith generate a static site with a blog in a subdirectory?

I'm looking into Wintersmith-ifying my site, which is currently hand-written. I have a couple pages: index.html, projects.html, gpg.html, etc. I want to have a blog/ subdirectory, so that the final site looks like this:
.
|- index.html
|- gpg.html
|- project.html
|- blog/
| |- look-a-new-wintersmith-blog.md
| |- monkeys-are-really-cool.md
Is this possible? I've searched and looked at the Wintersmith documentation (and even the featured Wintersmith-powered sites), and come up with nothing. It seems like the only way is to have two instances of Wintersmith or something, but it also seems like there must be a better way.
You should get the desired result with something like this:
├── config.json <- site configuration
├── contents
│ ├── index.html <- these will just be outputted as-is
│ ├── gpg.html
│ ├── project.html
│ ├── blog <– each article has its own directory
│ │ ├── index.json <- this is your blog index at /blog/index.html
│ │ ├── look-a-new-wintersmith-blog
│ │ │ └── index.md
│ │ └── monkeys-are-really-cool
│ │ └── index.md
│ ├── authors <- author metadata, check author.jade
│ │ └── the-wintersmith.json
│ ├── css
│ │ └── main.css
│ └── feed.json
├── plugins
│ └── paginator.coffee <- paginator plugin
├── templates
│ ├── archive.jade
│ ├── article.jade
│ ├── author.jade
│ ├── feed.jade
│ ├── index.jade
│ └── layout.jade
└── views
└── articles.coffee <- view that lists articles
index.json is just a renamed and moved archive.json to give a /blog/index.html URL instead. If you want the default Wintersmith index instead of an archive layout, edit the file to use the index.jade layout instead of archive.jade.
If you change your current HTML files to Markdown and put them in the same spot, then they'll be outputted as HTML as your blog posts would.
You might want to add some sort of navigation menu to your article layout, too.
Edit: To create a static page, create a Markdown file in contents similar to the following:
---
title: GPG
author: baker
date: 2014-03-23
template: article.jade
---
Content
If you named this file gpg.md, it should be accessible at http://localhost:8080/gpg.html. Because we used the article.jade template, it expects an author and a date field for completeness (it would work without, however it would still include "Written by" without an author), but you could make a custom template that doesn't use those fields.