How to link my .h and .c files in the same project but different directory using CMake - eclipse

I'm currently working on an embedded C project in Eclipse, cross-compiling to an M4 Cortex target. This project will create 3 separate executable files: apple.hex, orange.hex, and pear.hex. The "apple" source directory compiles, builds, and links without any dependencies on "orange" or "pear". The "orange" source directory also compiles, builds, and links without any dependencies.
However, "pear" needs to access numerous .h and .c assets from "orange". I've had many attempts at getting my CMakeLists.txt to "find" and "link" the code from "orange" to "pear", but to no avail.
Here is my current CMakeLists.txt file:
cmake_minimum_required(VERSION 3.0)
file(GLOB LD_FILE *gcc_nrf52.ld)
set(MY_APP_DIR ${CMAKE_SOURCE_DIR}/apps/orange)
create_application(
NAME
"pear"
PLATFORM
target
INCLUDE_DIRS
./
${MY_APP_DIR}
LINKER_SCRIPT
${LD_FILE}
SOURCES
${MY_APP_DIR}/foo.c
${MY_APP_DIR}/foo_bar.c
main.c
LIBRARIES
SomeLib_1
SomeLib_2
SomeLib_3
)
However, the compiler keeps complaining, saying that it cannot find "foo.h" and "foo_bar.h".
1) Do I need to separately create a static library in orange in order to access it in pear?
2) If I don't need to create a static library to access orange from pear, how do I link orange to pear?
3) I cannot find where CMake places the object files. Where are they?
This project is all under a single makefile.
Any help would be greatly appreciated, thanks!
I was able to fix my directory issues so that all of the include directories in ${MY_APP_DIR} are being linked into "Pear". However, a new issues has arisen. The linker cannot find the map file needed to create the executable image:
/usr/local/Caskroom/gcc-arm-embedded/5_4-2016q3,20160926/gcc-arm-none-eabi-5_4-2016q3/bin/../lib/gcc/arm-none-eabi/5.4.1/../../../../arm-none-eabi/bin/ld: cannot open map file /Users/admin/Github/target/apps/pear/pear.map: No such file or directory.
I'm not sure why a map find isn't being created. Is the linker (ld) still missing files?

I'll try to answer your questions
You are not linking your libraries to your target.
You need something like:
$target_link_libraries(yourtarget yourlibraries)
after your add_executable command.
3) I cannot find where CMake places the object files. Where are they?
CMake puts all of its outputs in the build tree by default, so unless you are liberally using ${CMAKE_SOURCE_DIR} or ${CMAKE_CURRENT_SOURCE_DIR} in your cmake files, you should find the output files in the folder where your CMakeLists.txt file is.

Related

CMake under eclipse - locate linked files and libraries from other non-cmake projects

I got a following problem. We have a very silly git structure and guidelines, so my eclipse projects use linked files. I have to make google tests for the projects, and the only way I found it to work is to use cmake. However, the test files are not in workspace but in a git repository and only linked to eclipse project. I cant figure out how to make CMakeLists.txt to follow the files.... I tried using include_directories with either relative or absolute paths..
Errors I get:
mingw32-make.exe[2]: *** No rule to make target 'C:/Users/name/eclipse-
workspace/MyTestCmake/Solver_test.cpp', needed by 'CMakeFiles/Solver_test.dir/Solver_test.cpp.obj'. Stop.
mingw32-make.exe[1]: *** [CMakeFiles\Makefile2:164: CMakeFiles/Solver_test.dir/all] Error 2
mingw32-make.exe: *** [Makefile:145: all] Error 2
Another question is - one of the libraries is built without cmake. How can I specify the path to it, where the cmake should find it?
Current Cmakelists.txt:
cmake_minimum_required(VERSION 3.14)
project (RadiTestCmake)
include(FetchContent)
FetchContent_Declare(googletest GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG release-1.12.1 )
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
enable_testing()
include_directories(
"${PROJECT_BINARY_DIR}"
"${PROJECT_BINARY_DIR}/../../../../../../gitlocal/backend/tests/"
)
add_executable(
hello_test
hello_test.cc
Solver_test.cpp
)
target_link_libraries(
hello_test
GTest::gtest_main
)
include(GoogleTest)
gtest_discover_tests(hello_test)

Programming Arduino with avrdude within Eclipse- cannot find -l/usr/avr

I am trying to program the Arudino Nano from Eclipse. It has the same processor as the Uno (Atmega328p). I have had this working before with the Uno, but have since gotten a new hard drive and had to reinstall/reconfigure everything. I am running Fedora 19 with Eclipse Kepler. I am getting an error in the build process that I don't even know where to start looking to solve, and Google hasn't been much help...
Here is the error:
make all
Building target: Arduino_Template.elf
Invoking: AVR C Linker
avr-gcc -Wl,-Map,Arduino_Template.map -mmcu=atmega328p -o "Arduino_Template.elf" ./Analog.o -l/usr/avr
/usr/lib/gcc/avr/4.8.2/../../../../avr/bin/ld: cannot find -l/usr/avr
collect2: error: ld returned 1 exit status
make: *** [Arduino_Template.elf] Error 1
17:29:38 Build Finished (took 124ms)
Has anyone encountered this before? Or does anyone have any suggestions?
Thanks.
The problem could be described like this:
First, the library should be specified only by its name and without the "lib" prefix and the ".a" suffix. The linker (this is where you get the error) will look for the library within the specified in the project paths and will add whatever is necessary to the file library name. So if the library you need is named mystuff it will look for a file named libmystuff.a.
In your case this is specified by the -l/usr/avr which I think could be misconfiguration or you did not copy/paste the entire error output. With the '-l' option you specify the name only, not the entire path to the file.
Second, the path should be specified, in the project configuration, where to look for the libraries, otherwise the linker will look for the library files only within your own project only. Often libraries are part of another project - so you need to adjust the project configuration accordingly.
I had similar problem and this is how I solved it ...
Go to menu Project/Properties. On left - choose "C/C++ Build". On right - choose the tab "Tool Settings". On the tree view choose "AVR C Linker" then "Libraries" sub-item. You are where you may need to make changes.
The list of "Libraries" is where you add libraries names, such as mystuff.
The Libraries Path is where you specify the paths to the libraries. This may look like this: "${workspace_loc:/mystuff/Release}"
The result of this is that the linker will look for this file: /mystuff/Release/libmystuff.a under you workspace root folder.

Using CMake to index source files of an external library with Eclipse

I am using CMake to build a project with external libraries by using "Eclipse CDT4 - Unix Makefiles".
Importing in Eclipse leads to a working project, but only all header files and my implemented source files are recognized correctly by the index of Eclipse.
I would also like to navigate through the source files for one external library by using "ctrl+click". I don't know how to add the *.cpp files of that external library in my CMakeList.txt to get them recognized by the indexer without building the library.
You can mark the .cpp files as "header file only" like this:
# find all filenames in the lib path and gather them in $YOUR_LIB
FILE(GLOB YOUR_LIB path_to_library/*.?pp)
# create a seperate sourcegroup so it doesn't clutter up the rest of your code
SOURCE_GROUP(\\lib FILES ${YOUR_LIB})
# mark them as header-file only
SET_SOURCE_FILES_PROPERTIES(${YOUR_LIB} PROPERTIES HEADER_FILE_ONLY TRUE)
# add both your code and the lib-code to the project
ADD_EXECUTABLE(program ${YOUR_CODE} ${YOUR_LIB})
I found a way to attach external library source files to the Eclipse project that is compatible with CMake project generator.
It turns out that to indexing and "ctrl+click" navigation works correctly only when external library sources are direct descendants of the project source folder. Therefore the solution is following:
Scan external library folder for source files.
Create a child folder under project's source folder.
Symlink discovered sources inside the created folder.
I created a CMake function attachExternalSources that performs above steps:
function(attachExternalSources librarySourceLocation folderName)
# Create folder for Geant4 sources
file(MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/${folderName})
message(STATUS "Searching for C++ sources in \"${librarySourceLocation}\"...")
FILE(GLOB_RECURSE libSources
${librarySourceLocation}/*.c
${librarySourceLocation}/*.cpp
${librarySourceLocation}/*.cxx
${librarySourceLocation}/*.cc
)
message(STATUS "Symlinking sources into\n \"${CMAKE_SOURCE_DIR}/${folderName}\"\n Please wait...")
foreach(source ${libSources})
# Obtain source filename
get_filename_component(source_filename ${source} NAME)
# Create symlink unless it already exists
set(symlink "${CMAKE_SOURCE_DIR}/${folderName}/${source_filename}")
if(NOT EXISTS ${symlink})
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ${source} ${symlink})
endif()
endforeach()
# Scan all the symlinks created under the project folder and disable their compilation
FILE(GLOB sources_symlinks ${CMAKE_SOURCE_DIR}/${folderName}/*)
SET_SOURCE_FILES_PROPERTIES(${sources_symlinks} PROPERTIES HEADER_FILE_ONLY TRUE)
endfunction()
The use of the function is following. Paste above function code in your CMakeLists.txt. Next, use it as follows:
attachExternalSources("path/to/external/library/sources" "library-sources")
First parameter is location of the external library source code. Second argument is the name of a folder inside your project that that will contain source symlinks.
P.S. I tested function with Eclipse 4.19 and CMake 3.20.5.

Cedet Help: Configuring a "Make" project

I am learning cedet for my c/c++ projects. However, I am facing difficulty in Make projects.
Say I have a file
main.cpp that looks like this
//main.cpp
#include "temp.h"
blah... <c++ code>
and I have temp.h and temp.cpp
that look like this
//temp.h
some declarations
//temp.cpp
some definitions
Then in emacs+cedet, I do ede-new and then I add a target main using ede-new-target and add main.cpp to main.
Then I write temp.h and temp.cpp and add temp.cpp to target temp.
I choose all targets as program generating this Project.ede file
;; Object Test
;; EDE project file.
(ede-proj-project "Test"
:name "Test"
:file "Project.ede"
:targets (list
(ede-proj-target-makefile-program "main"
:name "main"
:path ""
:source '("main.cpp")
)
(ede-proj-target-makefile-program "temp"
:name "temp"
:path ""
:source '("temp.cpp")
)
)
)
Now when I generate the makefile using ede-proj-regenerate, it creates a Makefile that generates main.o and temp.o
The make however fails as the Makefile generated does not identify the dependency of main.cpp on temp.cpp. How can I tell cedet EDE to identify this dependency? What is wrong in what I am doing here?
And secondly, how do I tell it that I do not want main.o as this is the final target program/executable and not an object file.
For your example, the created Makefile should be creating both main.o, and main. The name of the target you create should be the name of your program, so if you changed the target named "main" to "Pickle", it will create a main.o, and a Pickle program.
When you edit temp.cpp, you should add it to main, or Pickle if you choose to rename the target. Put all your source files for the program into the single target, unless you are choosing to create a library, in which case add temp to a library type target instead.
To "Fix things up", you can use the customize-project command to access all the other options not usually available via simple commands from Emacs proper. That will let you add dependencies on libraries, add your headers as aux src, and other useful things. Just read the doc strings associated with the different options.
A quick start for EDE can be found here.

What is the difference between building C++ Builder project from IDE and command line?

I have different behaviour of compiler, when building project from IDE and from command-line, which I can not explain.
The detailed issue's description is rather big, but it's really simple.
I have a C++ Builder project, which has a PAS-file included (IncludeUnits.pas). This pas-file has several units and inc-files listed. These files are located in separate folders and these folders are listed in library&include paths in project's options.
Folders layout:
C:\Demo\Bin
C:\Demo\Project
C:\Demo\Project\CBuilder5
C:\Demo\Project\Common
C:\Demo\Source
C:\Demo\Source\Common
Bin is output folder, Project/CBuilder5 holds project (bpr-file), Project/Common holds included pas-file (IncludeUnits.pas), Source and Source/Common hold other files (pas&inc). I think that it's pretty usual layout.
C:\Demo\Project\Common\ IncludeUnits.pas :
unit IncludeUnits;
interface
uses
Test;
implementation
end.
C:\Demo\Source\ Test.pas :
unit Test;
interface
{$I Test.inc}
implementation
end.
C:\Demo\Source\Common\ Test.inc :
// this file is empty
If I compile this project from C++ Builder IDE - it will compile fine. C++ Builder IDE doesn't have any additional paths in IDE settings set.
Now, I want to compile it from command-line. First, I issue
bpr2mak.exe MyProject.bpr
command.
This command creates MyProject.mak file, where I can see all paths ("....\Source" and "....\Source\Common" are the paths in question):
...
INCLUDEPATH = $(BCB)\include;$(BCB)\include\vcl;..\Common;..\..\Source;..\..\Source\Common
LIBPATH = $(BCB)\lib\obj;$(BCB)\lib;..\Common;..\..\Source;..\..\Source\Common
...
Now, I run make command:
make.exe -B -f"MyProject.mak"
It gives me the following output:
C:\PROGRA~1\Borland\CBUILD~2\BIN\dcc32 -N2....\Bin -N0....\Bin -$Y+ -$W -$R -v -JPHNE -M -UC:\PROGRA~1\Borland\CBUILD~2\bin..\include;C:\PROGRA~1\Borland\CBUILD~2\bin..\include\vcl;..\Common;..\..\Source;..\..\Source\Common -D_DEBUG;_RTLDLL;NO_STRICT -OC:\PROGRA~1\Borland\CBUILD~2\bin..\include;C:\PROGRA~1\Borland\CBUILD~2\bin..\include\vcl;..\Common;..\..\Source;..\..\Source\Common --BCB ..\Common\IncludeUnits.PAS
Borland Delphi Version 13.0 Copyright (c) 1983,99 Inprise Corporation
C:\Demo\Project\Common\IncludeUnits.pas(1) C:\Demo\Project\Common\IncludeUnits.pas(1) C:\Demo\Project\Common\IncludeUnits.pas(1) C:\Demo\Project\Common\IncludeUnits.pas(6) C:\Demo\Source\Test.pas(1) C:\Demo\Source\Test.pas(5) Fatal: File not found: 'Test.inc'
As you can see - all search path is passed to compiler and the file (Test.inc) is all here - in that Source\Common folder. But still compiler can't find it?
Of course, I run both commands from folder with bpr-file. And changing paths to absolute doesn't help.
Copying Test.inc from Source\Common to Source will help. Changing {$I Test.inc} to {$I Common\Test.inc} will also help.
Why? It seems that I'm missing something. Remember: project have no problems with compiling from IDE, Test.inc is found without copying or changing declaration. Did I miss some switch to make or dcc32?
I found the reason: command line for dcc32 misses -I switch, which specifies paths for include files.
For some reason, bpr2mak doesn't respect this option. Fortunately, it allows you to specify alternate template for conversion bpr -> mak. I edited default template and added "-I" option to it, pass new template to bpr2mak - and it worked.