Skip to content

Commit

Permalink
cmake: Allow out-of-tree builds (aardappel#201)
Browse files Browse the repository at this point in the history
* cmake: Allow out-of-tree builds

This is a best practice, allowing easier development (not having to worry about cleaning the source directory).

* cmake: Install desktop file to proper location

* cmake: Install locales to correct platform paths on Linux

We still need to keep MyApp::AddTranslation for cases when the app
is built with something other than CMake, and on other platforms than Linux.

We are also adding a TREESHEETS_RELOCATABLE_INSTALLATION CMake configuration flag
that allows installing to the old relocatable location even on Linux.

Finally, we only install the necessary `*.mo` files, not the `*.po` files or `*.bat` helper scripts.

* cmake: Add support for FHS paths for docs and data

This is needed to make Linux distributions happy.

Had to bump minimum macOS version to Catalina since std::filesystem::path
is not supported on older versions than 10.15. macOS 10.14 (Mojave)
is unsupported since October 2021.
  • Loading branch information
jtojnar authored Mar 12, 2022
1 parent 3193b88 commit 4f4ff4b
Show file tree
Hide file tree
Showing 12 changed files with 138 additions and 57 deletions.
8 changes: 5 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,16 @@ jobs:
cd wxWidgets/build_
sudo make install
- name: cmake
run: CXX=${{ matrix.cxx }} cmake -DCMAKE_BUILD_TYPE=Release .
run: CXX=${{ matrix.cxx }} cmake -S . -B _build -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=TreeSheets-relocatable -DTREESHEETS_RELOCATABLE_INSTALLATION=ON
- name: build TreeSheets
run: make -j4
run: make -C _build -j4
- name: install files
run: make -C _build install
- name: upload build artifacts
uses: actions/upload-artifact@v1
with:
name: Linux TreeSheets ${{ matrix.cxx }}
path: TS
path: TreeSheets-relocatable

build-windows:
name: Build Windows
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,18 @@ TreeSheets/\.vs/treesheets/v15/
build/treesheets/language/

TS/scripts/\.con\.log
# In-tree build
TS/treesheets
TS/2

# In-tree build CMake files
CMakeCache.txt
CMakeFiles/**
Makefile
cmake_install.cmake
CMakeLists.txt.user
# Build directory for out-of-tree builds
_build/

TreeSheets/.vs

Expand Down
24 changes: 3 additions & 21 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,29 +83,11 @@ script:
if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
xcodebuild -project osx/TreeSheets/TreeSheets.xcodeproj
elif [[ "$TRAVIS_OS_NAME" == "linux" && "$WXLIB" == "libwxgtk3.0-dev" ]]; then
cmake . -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
make -j$(nproc)
make DESTDIR=appdir -j$(nproc) install
cmake -S . -C _build -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
make -C _build -j$(nproc)
make -C _build DESTDIR=appdir -j$(nproc) install
wget -c -nv "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage"
chmod a+x linuxdeployqt-continuous-x86_64.AppImage
# FIXME: The following reshuffling can be removed once https://github.com/aardappel/treesheets/issues/133 is resolved
mkdir -p appdir/usr/share/applications # FIXME
mv appdir/usr/treesheets.desktop appdir/usr/share/applications/ # FIXME
sed -i -e 's|^Exec=.*|Exec=treesheets|g' appdir/usr/share/applications/treesheets.desktop
sed -i -e 's|^Icon=.*|Icon=treesheets|g' appdir/usr/share/applications/treesheets.desktop
mkdir -p appdir/usr/bin/ # FIXME
mv appdir/usr/docs appdir/usr/bin/ # FIXME
mv appdir/usr/examples appdir/usr/bin/ # FIXME
mv appdir/usr/treesheets appdir/usr/bin/ # FIXME
mv appdir/usr/translations appdir/usr/bin/ # FIXME
strip TS/treesheets # FIXME
cp TS/treesheets appdir/usr/bin/ # FIXME
ls -lh appdir/usr/bin/treesheets && chmod a+x appdir/usr/bin/treesheets
mv appdir/usr/scripts appdir/usr/bin/ # FIXME
mv appdir/usr/images appdir/usr/bin/ # FIXME
mkdir -p appdir/usr/share/icons/hicolor/scalable/apps/ # FIXME
cp appdir/usr/bin/images/treesheets.svg appdir/usr/share/icons/hicolor/scalable/apps/ # FIXME
( cd appdir ; ln -s usr/bin/docs/ usr/bin/examples/ usr/bin/images/ usr/bin/scripts/ usr/bin/translations/ . )
sed -i -e 's|1011|1002|g' appdir/usr/bin/treesheets # https://github.com/aardappel/treesheets/issues/130#issuecomment-528075693
# Workaround to increase compatibility with older systems; see https://github.com/darealshinji/AppImageKit-checkrt for details
mkdir -p appdir/usr/optional/ ; wget -c https://github.com/darealshinji/AppImageKit-checkrt/releases/download/continuous/exec-x86_64.so -O ./appdir/usr/optional/exec.so
Expand Down
75 changes: 67 additions & 8 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
# Sample build with makefile generator
#
# cd <into-treesheets-source>
# cmake -H. -Bb -DCMAKE_BUILD_TYPE=Release \
# cmake . -B _build -DCMAKE_BUILD_TYPE=Release \
# -DCMAKE_INSTALL_PREFIX=installed \
# -DCMAKE_PROGRAM_PATH=<path-to-wx-config> # not always needed
# cmake --build b --target install
# cmake --build _build --target install
#
# Sample build with IDE generator, like Xcode
#
# cd <into-treesheets-source>
# cmake -H. -Bb -GXcode \
# cmake -B _build -GXcode \
# -DCMAKE_PROGRAM_PATH=<path-to-wx-config> # not always needed
# cmake --build b --config Release --target install
# cmake --build _build --config Release --target install
#
# Run program:
#
Expand All @@ -24,11 +25,15 @@ cmake_minimum_required(VERSION 3.1)

project(treesheets)

if(NOT APPLE AND NOT WIN32)
set(TREESHEETS_RELOCATABLE_INSTALLATION OFF CACHE BOOL "Install data relative to the treesheets binary, instead of respecting the Filesystem Hierarchy Standard")

include(GNUInstallDirs)
endif()

# set(CMAKE_CXX_STANDARD 17) # this doesn't work correctly on all CMake versions :(
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/TS)

find_package(wxWidgets REQUIRED aui adv core xml net)
include(${wxWidgets_USE_FILE})

Expand All @@ -47,6 +52,60 @@ include_directories(lobster/include lobster/src)
add_executable(treesheets ${sources})

target_link_libraries(treesheets PRIVATE ${wxWidgets_LIBRARIES})
if(NOT APPLE AND NOT WIN32 AND NOT TREESHEETS_RELOCATABLE_INSTALLATION)
set(TREESHEETS_BINDIR ${CMAKE_INSTALL_BINDIR})
set(TREESHEETS_DOCDIR ${CMAKE_INSTALL_DOCDIR})
set(TREESHEETS_FULL_DOCDIR ${CMAKE_INSTALL_FULL_DOCDIR})
set(TREESHEETS_PKGDATADIR ${CMAKE_INSTALL_DATADIR}/${CMAKE_PROJECT_NAME})
set(TREESHEETS_FULL_PKGDATADIR ${CMAKE_INSTALL_FULL_DATADIR}/${CMAKE_PROJECT_NAME})

# Apple and Windows always look to relative paths for locales.
target_compile_definitions(treesheets PRIVATE "LOCALEDIR=L\"${CMAKE_INSTALL_FULL_LOCALEDIR}\"")
target_compile_definitions(treesheets PRIVATE "TREESHEETS_DOCDIR=\"${TREESHEETS_FULL_DOCDIR}\"")
target_compile_definitions(treesheets PRIVATE "TREESHEETS_DATADIR=\"${TREESHEETS_FULL_PKGDATADIR}\"")
else()
set(TREESHEETS_BINDIR ${CMAKE_INSTALL_PREFIX})
set(TREESHEETS_DOCDIR ${CMAKE_INSTALL_PREFIX})
set(TREESHEETS_PKGDATADIR ${CMAKE_INSTALL_PREFIX})
endif()

install(TARGETS treesheets DESTINATION ${TREESHEETS_BINDIR})
install(DIRECTORY TS/docs DESTINATION ${TREESHEETS_DOCDIR})
install(FILES TS/readme.html DESTINATION ${TREESHEETS_DOCDIR})
install(DIRECTORY TS/examples DESTINATION ${TREESHEETS_DOCDIR})

install(DIRECTORY TS/images DESTINATION ${TREESHEETS_PKGDATADIR})
install(DIRECTORY TS/scripts DESTINATION ${TREESHEETS_PKGDATADIR})

# Install translations to correct platform-specific path.
# See: https://docs.wxwidgets.org/trunk/overview_i18n.html#overview_i18n_mofiles
file(
GLOB locales
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/TS/translations
TS/translations/*/ts.mo
)
list(
TRANSFORM locales
REPLACE "/ts\\.mo$" ""
)
if(APPLE OR WIN32 OR TREESHEETS_RELOCATABLE_INSTALLATION)
foreach(locale ${locales})
install(
FILES "TS/translations/${locale}/ts.mo"
DESTINATION "${CMAKE_INSTALL_PREFIX}/translations/${locale}"
)
endforeach()
else()
# Falling back to GNU scheme
foreach(locale ${locales})
install(
FILES "TS/translations/${locale}/ts.mo"
DESTINATION "${CMAKE_INSTALL_LOCALEDIR}/${locale}/LC_MESSAGES"
)
endforeach()
endif()

install(TARGETS treesheets DESTINATION .)
install(DIRECTORY TS/ DESTINATION .)
if(NOT APPLE AND NOT WIN32)
install(FILES TS/images/treesheets.svg DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/scalable/apps)
install(FILES TS/treesheets.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications)
endif()
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ Linux:
- Using the version of wxWidgets from https://github.com/wxWidgets/wxWidgets.git
- Follow the instructions to build there, but add `--enable-unicode` and
`--disabled-shared` to the `configure` step.
- Build with `cmake -DCMAKE_BUILD_TYPE=Release .` or similar. Note that you must
currently use an "in tree" build, since TreeSheets will look for its files
relative to the binary.
- Build with `cmake -S . -B _build -DCMAKE_BUILD_TYPE=Release` or similar.
You can change the default installation prefix (`/usr/local`) by passing something like `-DCMAKE_INSTALL_PREFIX=/usr`.
- Install using `sudo make -C _build install`.
- There is also a `src/Makefile`, this is deprecated.

OSX:
Expand Down
8 changes: 4 additions & 4 deletions osx/TreeSheets/TreeSheets.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@
../../lobster/include,
);
LIBRARY_SEARCH_PATHS = "";
MACOSX_DEPLOYMENT_TARGET = 10.12;
MACOSX_DEPLOYMENT_TARGET = 10.15;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
USER_HEADER_SEARCH_PATHS = "../../lobster/src ../../lobster/include";
Expand Down Expand Up @@ -459,7 +459,7 @@
../../lobster/include,
);
LIBRARY_SEARCH_PATHS = "";
MACOSX_DEPLOYMENT_TARGET = 10.12;
MACOSX_DEPLOYMENT_TARGET = 10.15;
SDKROOT = macosx;
USER_HEADER_SEARCH_PATHS = "../../lobster/src ../../lobster/include";
VALID_ARCHS = x86_64;
Expand Down Expand Up @@ -491,7 +491,7 @@
"/usr/local/include/wx-3.1",
);
INFOPLIST_FILE = "TreeSheets/TreeSheets-Info.plist";
MACOSX_DEPLOYMENT_TARGET = 10.12;
MACOSX_DEPLOYMENT_TARGET = 10.15;
OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)";
OTHER_LDFLAGS = (
"-L/usr/local/lib",
Expand Down Expand Up @@ -544,7 +544,7 @@
"/usr/local/include/wx-3.1",
);
INFOPLIST_FILE = "TreeSheets/TreeSheets-Info.plist";
MACOSX_DEPLOYMENT_TARGET = 10.12;
MACOSX_DEPLOYMENT_TARGET = 10.15;
OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)";
OTHER_LDFLAGS = (
"-L/usr/local/lib",
Expand Down
4 changes: 2 additions & 2 deletions src/document.h
Original file line number Diff line number Diff line change
Expand Up @@ -919,9 +919,9 @@ struct Document {
case A_HELP:
#ifdef __WXMAC__
wxLaunchDefaultBrowser(L"file://" +
sys->frame->GetPath(L"docs/tutorial.html")); // RbrtPntn
sys->frame->GetDocPath(L"docs/tutorial.html")); // RbrtPntn
#else
wxLaunchDefaultBrowser(sys->frame->GetPath(L"docs/tutorial.html"));
wxLaunchDefaultBrowser(sys->frame->GetDocPath(L"docs/tutorial.html"));
#endif
return nullptr;

Expand Down
3 changes: 3 additions & 0 deletions src/myapp.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ struct MyApp : wxApp {
#ifdef __WXGTK__
locale.AddCatalogLookupPathPrefix(L"/usr");
locale.AddCatalogLookupPathPrefix(L"/usr/local");
#ifdef LOCALEDIR
locale.AddCatalogLookupPathPrefix(LOCALEDIR);
#endif
wxString prefix = wxStandardPaths::Get().GetInstallPrefix();
locale.AddCatalogLookupPathPrefix(prefix);
#endif
Expand Down
54 changes: 42 additions & 12 deletions src/myframe.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,39 @@ struct MyFrame : wxFrame {
ColorDropdown *textdd = nullptr;
ColorDropdown *borddd = nullptr;

wxString GetPath(const wxString &relpath) {
if (!exepath_.Length()) return relpath;
return exepath_ + "/" + relpath;
wxString GetDocPath(const wxString &relpath) {
std::filesystem::path candidatePaths[] = {
std::filesystem::path(exepath_.Length() ? exepath_.ToStdString() + "/" + relpath.ToStdString() : relpath.ToStdString()),
#ifdef TREESHEETS_DOCDIR
std::filesystem::path(TREESHEETS_DOCDIR "/" + relpath.ToStdString()),
#endif
};
std::filesystem::path relativePath;
for (auto path : candidatePaths) {
relativePath = path;
if (std::filesystem::exists(relativePath)) {
break;
}
}

return wxString(relativePath.c_str());
}
wxString GetDataPath(const wxString &relpath) {
std::filesystem::path candidatePaths[] = {
std::filesystem::path(exepath_.Length() ? exepath_.ToStdString() + "/" + relpath.ToStdString() : relpath.ToStdString()),
#ifdef TREESHEETS_DATADIR
std::filesystem::path(TREESHEETS_DATADIR "/" + relpath.ToStdString()),
#endif
};
std::filesystem::path relativePath;
for (auto path : candidatePaths) {
relativePath = path;
if (std::filesystem::exists(relativePath)) {
break;
}
}

return wxString(relativePath.c_str());
}

MenuString menustrings;
Expand Down Expand Up @@ -91,7 +121,7 @@ struct MyFrame : wxFrame {

wxLogMessage(L"locale: %s", std::setlocale(LC_CTYPE, nullptr));

app->AddTranslation(GetPath("translations"));
app->AddTranslation(GetDataPath("translations"));

csf = GetContentScaleFactor();
wxLogMessage(L"content scale: %f", csf);
Expand Down Expand Up @@ -121,8 +151,8 @@ struct MyFrame : wxFrame {

wxIconBundle icons;
wxIcon iconbig;
icon.LoadFile(GetPath(L"images/icon16.png"), wxBITMAP_TYPE_PNG);
iconbig.LoadFile(GetPath(L"images/icon32.png"), wxBITMAP_TYPE_PNG);
icon.LoadFile(GetDataPath(L"images/icon16.png"), wxBITMAP_TYPE_PNG);
iconbig.LoadFile(GetDataPath(L"images/icon32.png"), wxBITMAP_TYPE_PNG);
if (!icon.IsOk() || !iconbig.IsOk()) {
wxMessageBox(_(L"Error loading core data file (TreeSheets not installed correctly?)"),
_(L"Initialization Error"), wxOK, this);
Expand All @@ -139,9 +169,9 @@ struct MyFrame : wxFrame {
SetIcons(icons);

wxImage foldiconi;
line_nw.LoadFile(GetPath(L"images/render/line_nw.png"), wxBITMAP_TYPE_PNG);
line_sw.LoadFile(GetPath(L"images/render/line_sw.png"), wxBITMAP_TYPE_PNG);
foldiconi.LoadFile(GetPath(L"images/nuvola/fold.png"));
line_nw.LoadFile(GetDataPath(L"images/render/line_nw.png"), wxBITMAP_TYPE_PNG);
line_sw.LoadFile(GetDataPath(L"images/render/line_sw.png"), wxBITMAP_TYPE_PNG);
foldiconi.LoadFile(GetDataPath(L"images/nuvola/fold.png"));
foldicon = wxBitmap(foldiconi);
ScaleBitmap(foldicon, csf / 3.0, foldicon);

Expand Down Expand Up @@ -547,7 +577,7 @@ struct MyFrame : wxFrame {
optmenu->AppendSubMenu(roundmenu, _(L"&Roundness of grid borders..."));

wxMenu *scriptmenu = new wxMenu();
auto scriptpath = GetPath("scripts/");
auto scriptpath = GetDataPath("scripts/");
wxString sf = wxFindFirstFile(scriptpath + L"*.lobster");
int sidx = 0;
while (!sf.empty()) {
Expand Down Expand Up @@ -630,7 +660,7 @@ struct MyFrame : wxFrame {
#endif

wxString iconpath =
GetPath(iconset ? L"images/webalys/toolbar/" : L"images/nuvola/toolbar/");
GetDataPath(iconset ? L"images/webalys/toolbar/" : L"images/nuvola/toolbar/");
auto sz = (iconset ? wxSize(18, 18) : wxSize(22, 22)) * csf;
tb->SetToolBitmapSize(sz);

Expand Down Expand Up @@ -684,7 +714,7 @@ struct MyFrame : wxFrame {
tb->AddControl(borddd);
tb->AddSeparator();
tb->AddControl(new wxStaticText(tb, wxID_ANY, _(L"Image ")));
wxString imagepath = GetPath("images/nuvola/dropdown/");
wxString imagepath = GetDataPath("images/nuvola/dropdown/");
idd = new ImageDropdown(tb, imagepath);
tb->AddControl(idd);
tb->Realize();
Expand Down
1 change: 1 addition & 0 deletions src/stdafx.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ WX_DECLARE_STRING_HASH_MAP(bool, wxHashMapBool);
#include <algorithm>
#include <memory>

#include <filesystem>
#include <utility>

#include <locale>
Expand Down
6 changes: 3 additions & 3 deletions src/system.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,12 +198,12 @@ struct System {
void LoadTut() {
auto lang = frame->app->locale.GetCanonicalName();
lang.Truncate(2);
if (LoadDB(frame->GetPath(L"examples/tutorial-" + lang + ".cts"))[0]) {
LoadDB(frame->GetPath(L"examples/tutorial.cts"));
if (LoadDB(frame->GetDocPath(L"examples/tutorial-" + lang + ".cts"))[0]) {
LoadDB(frame->GetDocPath(L"examples/tutorial.cts"));
}
}

void LoadOpRef() { LoadDB(frame->GetPath(L"examples/operation-reference.cts")); }
void LoadOpRef() { LoadDB(frame->GetDocPath(L"examples/operation-reference.cts")); }

Cell *&InitDB(int sizex, int sizey = 0) {
Cell *c = new Cell(nullptr, nullptr, CT_DATA, new Grid(sizex, sizey ? sizey : sizex));
Expand Down
2 changes: 1 addition & 1 deletion src/treesheets_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ static int64_t TreeSheetsLoader(std::string_view absfilename, std::string *dest,
static TreeSheetsScriptImpl tssi;

static void ScriptInit(MyFrame *frame) {
auto serr = InitLobster(&tssi, frame->GetPath("scripts/"), "", false, TreeSheetsLoader);
auto serr = InitLobster(&tssi, frame->GetDataPath("scripts/"), "", false, TreeSheetsLoader);
if (!serr.empty())
frame->GetCurTab()->Status(wxString("Script system could not initialize: " + serr));
}

0 comments on commit 4f4ff4b

Please sign in to comment.